﻿// See https://aka.ms/new-console-template for more information
//解释器模式
//“解释器”和Google中的中英翻译功能类似。所以我们需要一个软件，可以把中英文互译，那彼此就可以更好的理解对方的意思，我感觉翻译软件也可以称得上是解释器，把你不懂的解释成你能理解的。我们写代码，需要编译器把我们写的代码编译成机器可以理解的机器语言，从这方面来讲，c#的编译器也是一种解释器。
//在软件构建过程中，如果某一特定领域的问题比较复杂，类似的模式不断重复出现，如果使用普通的编程方式来实现将面临非常频繁的变化。在这种情况下，将特定领域表达为某种语法规则下的句子，然后构建一个解释器来解释器这些句子，从而得到解决问题的目的。
//比如：用户只需要像计算机输入一个句子或者一个文件，计算就就可以按照事先定义好的文法规则对句子或者文件进行翻译，从而实现相对应的功能，例如一些游戏会存在一些玩家可以自定义的宏命令。

//在解释器模式的结构中有以下角色：
//·抽象表达式（AbstractExpression）：定义解释器的接口，约定解释器的解释操作。其中的Interpret接口，正如其名字那样，他是专门用来解释该解释器索要实现的功能。
//·终结符表达式（Terminal Expression）：实现了抽象表达式角色所要求的接口，主要是一个interpret（）方法；文法中的每一个终结符都有一个具体终结表达式与之相对应。比如有一个简单的公式R=R1+R2，在里面R1和R2就算终结符，对应的解释R1和R2的解释器就算终结符表达式。
//·非终结符表达式（Nonterminal Expression）：文法中的每一条规则都需要一个具体的非终结符表达式，非终结符表达式一般是文法中的运算符或者其他关键字，比如公式R=R1+R2中，“+”就算非终结符，解析“+”的解释器就算一个非终结符表达式。
//·环境角色（Context）：这个角色的任务一般是用来存放文法中各个终结符所对应的具体值，比如R=R1+R2，我们给R1赋值100，给R2赋值200.这些信息需要存放到环境角色中，很多情况下我们使用Map来充当环境角色就足够了。
//·客户端（Client）：指的是使用解释器的客户端，通常在这里将按照语言的语法做的表达式转换成使用解释器对象描述的抽象语法树，然后调用解释器操作。

//文法规则
//比如简单的加减法运算，我们定义一个这样的文法规则：
//·“表达式” 定义为 “值” 或者 “运算式”
//·“运算式” 定义为 “表达式+表达式” 或者 “表达式-表达式”
//·“值”定义为一个整数
//在解释器模式中，每一条文法规则都可以表示为一个类，因此可以方便的实现一个简单的语言。


//使用表达式
using System.Collections;

string roman = "七百六十八";
Context context=new Context(roman);
ArrayList tree=new ArrayList();
tree.Add(new GeExpression());
tree.Add(new ShiExpression());
tree.Add(new BaiExpression());

foreach(Expression exp in tree)
{
    exp.Interpreter(context);
}

Console.WriteLine(context.Data);

Console.Read();



Console.WriteLine("Hello, World!");

//环境上下文
public sealed class Context
{
    public string Statement { get; set; }
    public int Data { get; set; }

    public Context(string statement)
    {
        this.Statement = statement;
    }
}

//然后我们定义个抽象表达式树。我们把规则映射写道表达式树里面，里面定义了一个Interpreter方法用来解释输入的命令
//抽象表达式
public abstract class Expression
{
    private Dictionary<string, int> table = new Dictionary<string, int>();

    protected Expression()
    {
        table.Add("一", 1);
        table.Add("二", 2);
        table.Add("三", 3);
        table.Add("四", 4);
        table.Add("五", 5);
        table.Add("六", 6);
        table.Add("七", 7);
        table.Add("八", 8);
        table.Add("九", 9);
    }

    public virtual void Interpreter(Context context)
    {
        if (context.Statement.Length == 0)
        {
            return;
        }

        foreach (var key in table.Keys)
        {
            int value = table[key];

            //核心实现
            if (context.Statement.EndsWith(key + GetPostFix()))//【重点理解】如果以五（十）/六（百）结尾 key=五，六：GetPostFix=十，百
            {
                context.Data += value * this.Multiplier();
                context.Statement = context.Statement.Substring(0, context.Statement.Length - this.GetLength());//【重点理解】把刚刚处理的部分进行移除
            }
            if (context.Statement.EndsWith("零"))
            {
                context.Statement = context.Statement.Substring(0, context.Statement.Length - 1);
            }
        }
    }

    public abstract string GetPostFix();

    public abstract int Multiplier();

    //这个可以通用，但是对于各位数例外，所以用虚方法
    public virtual int GetLength()
    {
        return this.GetPostFix().Length + 1;
    }
}

//个位表达式
public sealed class GeExpression : Expression
{
    public override string GetPostFix()
    {
        return "";
    }
    public override int Multiplier()
    {
        return 1;
    }
    public override int GetLength()
    {
        return 1;
    }
}
//十位表达式
public sealed class ShiExpression : Expression
{
    public override string GetPostFix()
    {
        return "十";
    }
    public override int Multiplier()
    {
        return 10;
    }
}

//百位表达式
public sealed class BaiExpression : Expression
{
    public override string GetPostFix()
    {
        return "百";
    }
    public override int Multiplier()
    {
        return 100;
    }
}